<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网络架构图 - SVG实现</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background-color: rgba(255, 255, 255, 0.95);
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            padding: 25px;
            overflow: hidden;
        }

        header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 1px solid #eaeaea;
        }

        h1 {
            color: #2c3e50;
            font-size: 2.5rem;
            margin-bottom: 10px;
        }

        .description {
            color: #7f8c8d;
            font-size: 1.1rem;
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
        }

        .controls {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-bottom: 25px;
            flex-wrap: wrap;
        }

        button {
            background: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 50px;
            cursor: pointer;
            font-size: 1rem;
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        button:hover {
            background: #2980b9;
            transform: translateY(-2px);
            box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
        }

        .architecture-container {
            position: relative;
            min-height: 600px;
            border: 1px dashed #bdc3c7;
            border-radius: 8px;
            padding: 20px;
            background-color: #f9f9f9;
            overflow: auto;
        }

        #network-diagram {
            width: 100%;
            height: 100%;
            min-height: 550px;
        }

        .node {
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .node:hover {
            filter: brightness(1.2);
            transform: scale(1.05);
        }

        .node.active {
            filter: drop-shadow(0 0 8px #f1c40f);
        }

        .node-label {
            font-size: 12px;
            font-weight: bold;
            text-anchor: middle;
            pointer-events: none;
            fill: white;
        }

        .connection {
            stroke: #34495e;
            stroke-width: 2;
            fill: none;
            marker-end: url(#arrowhead);
        }

        .connection.active {
            stroke: #e74c3c;
            stroke-width: 3;
        }

        .info-panel {
            margin-top: 30px;
            padding: 20px;
            background-color: #ecf0f1;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            display: none;
        }

        .info-panel h3 {
            color: #2c3e50;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid #bdc3c7;
        }

        .info-content {
            line-height: 1.6;
        }

        footer {
            text-align: center;
            margin-top: 30px;
            color: #7f8c8d;
            font-size: 0.9rem;
        }

        .legend {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 15px;
            flex-wrap: wrap;
        }

        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 4px;
        }

        @media (max-width: 768px) {
            .controls {
                flex-direction: column;
                align-items: center;
            }

            button {
                width: 80%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>网络架构图 - SVG实现</h1>
            <p class="description">这是一个使用SVG和JavaScript创建的交互式网络架构图。SVG提供矢量图形支持，确保图像在任何缩放级别下都保持清晰。</p>
        </header>

        <div class="controls">
            <button id="resetBtn">重置视图</button>
            <button id="highlightBtn">高亮关键路径</button>
            <button id="addNodeBtn">添加节点</button>
            <button id="toggleConnectionsBtn">切换连接线</button>
            <button id="exportBtn">导出为PNG</button>
        </div>

        <div class="legend">
            <div class="legend-item">
                <div class="legend-color" style="background-color: #3498db;"></div>
                <span>网络设备</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background-color: #2ecc71;"></div>
                <span>服务器</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background-color: #9b59b6;"></div>
                <span>存储设备</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background-color: #e74c3c;"></div>
                <span>安全设备</span>
            </div>
        </div>

        <div class="architecture-container">
            <svg id="network-diagram" viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg">
                <!-- 定义箭头标记 -->
                <defs>
                    <marker id="arrowhead" markerWidth="10" markerHeight="7"
                    refX="9" refY="3.5" orient="auto">
                        <polygon points="0 0, 10 3.5, 0 7" fill="#34495e"/>
                    </marker>
                    <marker id="arrowhead-active" markerWidth="10" markerHeight="7"
                    refX="9" refY="3.5" orient="auto">
                        <polygon points="0 0, 10 3.5, 0 7" fill="#e74c3c"/>
                    </marker>

                    <!-- 渐变定义 -->
                    <linearGradient id="networkGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                        <stop offset="0%" stop-color="#3498db" />
                        <stop offset="100%" stop-color="#2980b9" />
                    </linearGradient>
                    <linearGradient id="serverGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                        <stop offset="0%" stop-color="#2ecc71" />
                        <stop offset="100%" stop-color="#27ae60" />
                    </linearGradient>
                    <linearGradient id="storageGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                        <stop offset="0%" stop-color="#9b59b6" />
                        <stop offset="100%" stop-color="#8e44ad" />
                    </linearGradient>
                    <linearGradient id="securityGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                        <stop offset="0%" stop-color="#e74c3c" />
                        <stop offset="100%" stop-color="#c0392b" />
                    </linearGradient>
                </defs>

                <!-- 连接线 -->
                <path id="conn1" class="connection" d="M200,150 L350,250" />
                <path id="conn2" class="connection" d="M200,150 L500,150" />
                <path id="conn3" class="connection" d="M350,250 L500,150" />
                <path id="conn4" class="connection" d="M500,150 L650,250" />
                <path id="conn5" class="connection" d="M650,250 L800,150" />
                <path id="conn6" class="connection" d="M350,250 L350,400" />
                <path id="conn7" class="connection" d="M650,250 L650,400" />
                <path id="conn8" class="connection" d="M350,400 L500,500" />
                <path id="conn9" class="connection" d="M650,400 L500,500" />

                <!-- 网络设备 -->
                <g class="node network-device" id="node1" data-type="router" data-info="核心路由器：处理所有网络流量，提供不同子网之间的连接。">
                    <rect x="150" y="100" width="100" height="100" rx="10" fill="url(#networkGradient)" />
                    <circle cx="175" cy="125" r="8" fill="#fff" />
                    <circle cx="200" cy="125" r="8" fill="#fff" />
                    <circle cx="225" cy="125" r="8" fill="#fff" />
                    <line x1="175" y1="140" x2="225" y2="170" stroke="#fff" stroke-width="2" />
                    <line x1="200" y1="140" x2="200" y2="170" stroke="#fff" stroke-width="2" />
                    <text class="node-label" x="200" y="190">核心路由器</text>
                </g>

                <g class="node network-device" id="node2" data-type="switch" data-info="接入交换机：连接终端设备到网络，提供局域网连接。">
                    <rect x="300" y="200" width="100" height="100" rx="10" fill="url(#networkGradient)" />
                    <rect x="320" y="220" width="60" height="40" fill="#fff" rx="5" />
                    <line x1="320" y1="240" x2="380" y2="240" stroke="#2c3e50" stroke-width="2" />
                    <line x1="340" y1="220" x2="340" y2="260" stroke="#2c3e50" stroke-width="2" />
                    <line x1="360" y1="220" x2="360" y2="260" stroke="#2c3e50" stroke-width="2" />
                    <text class="node-label" x="350" y="280">接入交换机</text>
                </g>

                <g class="node server" id="node3" data-type="server" data-info="Web服务器：托管网站和Web应用程序，处理HTTP/HTTPS请求。">
                    <rect x="450" y="100" width="100" height="100" rx="10" fill="url(#serverGradient)" />
                    <rect x="470" y="120" width="60" height="40" fill="#fff" rx="3" />
                    <line x1="485" y1="130" x2="515" y2="130" stroke="#2c3e50" stroke-width="1" />
                    <line x1="485" y1="140" x2="515" y2="140" stroke="#2c3e50" stroke-width="1" />
                    <line x1="485" y1="150" x2="515" y2="150" stroke="#2c3e50" stroke-width="1" />
                    <text class="node-label" x="500" y="190">Web服务器</text>
                </g>

                <g class="node network-device" id="node4" data-type="switch" data-info="核心交换机：连接网络中的关键设备，提供高速数据交换。">
                    <rect x="600" y="200" width="100" height="100" rx="10" fill="url(#networkGradient)" />
                    <rect x="620" y="220" width="60" height="40" fill="#fff" rx="5" />
                    <line x1="620" y1="240" x2="680" y2="240" stroke="#2c3e50" stroke-width="2" />
                    <line x1="640" y1="220" x2="640" y2="260" stroke="#2c3e50" stroke-width="2" />
                    <line x1="660" y1="220" x2="660" y2="260" stroke="#2c3e50" stroke-width="2" />
                    <text class="node-label" x="650" y="280">核心交换机</text>
                </g>

                <g class="node security" id="node5" data-type="firewall" data-info="防火墙：监控和控制网络流量，保护内部网络免受外部威胁。">
                    <rect x="750" y="100" width="100" height="100" rx="10" fill="url(#securityGradient)" />
                    <rect x="770" y="120" width="60" height="60" fill="#fff" rx="5" />
                    <line x1="770" y1="140" x2="830" y2="140" stroke="#c0392b" stroke-width="2" />
                    <line x1="770" y1="160" x2="830" y2="160" stroke="#c0392b" stroke-width="2" />
                    <text class="node-label" x="800" y="190">防火墙</text>
                </g>

                <!-- 存储设备 -->
                <g class="node storage" id="node6" data-type="nas" data-info="NAS存储：网络附加存储设备，提供文件级数据存储服务。">
                    <rect x="300" y="350" width="100" height="100" rx="10" fill="url(#storageGradient)" />
                    <rect x="320" y="370" width="60" height="50" fill="#fff" rx="3" />
                    <line x1="330" y1="380" x2="370" y2="380" stroke="#8e44ad" stroke-width="2" />
                    <line x1="330" y1="390" x2="370" y2="390" stroke="#8e44ad" stroke-width="2" />
                    <line x1="330" y1="400" x2="370" y2="400" stroke="#8e44ad" stroke-width="2" />
                    <text class="node-label" x="350" y="430">NAS存储</text>
                </g>

                <g class="node server" id="node7" data-type="dbserver" data-info="数据库服务器：存储和管理结构化数据，提供数据查询和处理服务。">
                    <rect x="600" y="350" width="100" height="100" rx="10" fill="url(#serverGradient)" />
                    <rect x="620" y="370" width="60" height="40" fill="#fff" rx="3" />
                    <line x1="635" y1="380" x2="665" y2="380" stroke="#2c3e50" stroke-width="1" />
                    <line x1="635" y1="390" x2="665" y2="390" stroke="#2c3e50" stroke-width="1" />
                    <line x1="635" y1="400" x2="665" y2="400" stroke="#2c3e50" stroke-width="1" />
                    <text class="node-label" x="650" y="430">数据库服务器</text>
                </g>

                <!-- 中央存储 -->
                <g class="node storage" id="node8" data-type="san" data-info="SAN存储：存储区域网络，提供块级数据存储服务，支持高性能应用。">
                    <rect x="450" y="450" width="100" height="100" rx="10" fill="url(#storageGradient)" />
                    <rect x="470" y="470" width="60" height="50" fill="#fff" rx="3" />
                    <line x1="480" y1="480" x2="520" y2="480" stroke="#8e44ad" stroke-width="2" />
                    <line x1="480" y1="490" x2="520" y2="490" stroke="#8e44ad" stroke-width="2" />
                    <line x1="480" y1="500" x2="520" y2="500" stroke="#8e44ad" stroke-width="2" />
                    <text class="node-label" x="500" y="530">SAN存储</text>
                </g>
            </svg>
        </div>

        <div class="info-panel" id="infoPanel">
            <h3>设备信息</h3>
            <div class="info-content" id="infoContent">
                点击网络架构图中的设备查看详细信息。
            </div>
        </div>

        <footer>
            <p>使用 SVG + JavaScript 构建 | 网络架构图示例</p>
        </footer>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const svg = document.getElementById('network-diagram');
            const nodes = document.querySelectorAll('.node');
            const connections = document.querySelectorAll('.connection');
            const infoPanel = document.getElementById('infoPanel');
            const infoContent = document.getElementById('infoContent');
            let connectionsVisible = true;

            // 节点点击事件
            nodes.forEach(node => {
                node.addEventListener('click', function() {
                    // 移除所有节点的active类
                    nodes.forEach(n => n.classList.remove('active'));
                    connections.forEach(c => c.classList.remove('active'));

                    // 为当前节点添加active类
                    this.classList.add('active');

                    // 高亮相关连接线
                    const nodeId = this.id;
                    highlightConnections(nodeId);

                    // 显示信息面板
                    infoPanel.style.display = 'block';

                    // 更新信息内容
                    const info = this.getAttribute('data-info');
                    infoContent.innerHTML = info;
                });
            });

            // 高亮与节点相关的连接线
            function highlightConnections(nodeId) {
                // 根据节点ID确定哪些连接线需要高亮
                const connectionMap = {
                    'node1': ['conn1', 'conn2'],
                    'node2': ['conn1', 'conn3', 'conn6'],
                    'node3': ['conn2', 'conn3', 'conn4'],
                    'node4': ['conn4', 'conn5', 'conn7'],
                    'node5': ['conn5'],
                    'node6': ['conn6', 'conn8'],
                    'node7': ['conn7', 'conn9'],
                    'node8': ['conn8', 'conn9']
                };

                if (connectionMap[nodeId]) {
                    connectionMap[nodeId].forEach(connId => {
                        const conn = document.getElementById(connId);
                        if (conn) {
                            conn.classList.add('active');
                            conn.setAttribute('marker-end', 'url(#arrowhead-active)');
                        }
                    });
                }
            }

            // 重置视图
            document.getElementById('resetBtn').addEventListener('click', function() {
                nodes.forEach(node => node.classList.remove('active'));
                connections.forEach(conn => {
                    conn.classList.remove('active');
                    conn.setAttribute('marker-end', 'url(#arrowhead)');
                });
                infoPanel.style.display = 'none';
            });

            // 高亮关键路径
            document.getElementById('highlightBtn').addEventListener('click', function() {
                // 移除所有高亮
                nodes.forEach(node => node.classList.remove('active'));
                connections.forEach(conn => {
                    conn.classList.remove('active');
                    conn.setAttribute('marker-end', 'url(#arrowhead)');
                });

                // 高亮关键路径
                const criticalNodes = ['node1', 'node3', 'node5'];
                const criticalConnections = ['conn2', 'conn4', 'conn5'];

                criticalNodes.forEach(nodeId => {
                    const node = document.getElementById(nodeId);
                    if (node) node.classList.add('active');
                });

                criticalConnections.forEach(connId => {
                    const conn = document.getElementById(connId);
                    if (conn) {
                        conn.classList.add('active');
                        conn.setAttribute('marker-end', 'url(#arrowhead-active)');
                    }
                });

                // 显示信息
                infoPanel.style.display = 'block';
                infoContent.innerHTML = '关键路径：互联网 -> 核心路由器 -> Web服务器 -> 核心交换机 -> 防火墙 -> 互联网出口';
            });

            // 添加节点
            document.getElementById('addNodeBtn').addEventListener('click', function() {
                const nodeType = prompt("请选择节点类型 (network, server, storage, security):");
                const nodeName = prompt("请输入节点名称:");
                const nodeInfo = prompt("请输入节点描述:");

                if (nodeType && nodeName) {
                    // 创建新节点
                    const newNodeId = 'node' + (nodes.length + 1);
                    const x = Math.floor(Math.random() * 800) + 100;
                    const y = Math.floor(Math.random() * 400) + 100;

                    let fillColor, symbol;

                    switch(nodeType) {
                        case 'network':
                            fillColor = 'url(#networkGradient)';
                            symbol = createNetworkSymbol();
                            break;
                        case 'server':
                            fillColor = 'url(#serverGradient)';
                            symbol = createServerSymbol();
                            break;
                        case 'storage':
                            fillColor = 'url(#storageGradient)';
                            symbol = createStorageSymbol();
                            break;
                        case 'security':
                            fillColor = 'url(#securityGradient)';
                            symbol = createSecuritySymbol();
                            break;
                        default:
                            fillColor = 'url(#networkGradient)';
                            symbol = createNetworkSymbol();
                    }

                    const newNode = document.createElementNS('http://www.w3.org/2000/svg', 'g');
                    newNode.setAttribute('class', `node ${nodeType}`);
                    newNode.setAttribute('id', newNodeId);
                    newNode.setAttribute('data-info', nodeInfo || '新添加的节点');

                    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    rect.setAttribute('x', x);
                    rect.setAttribute('y', y);
                    rect.setAttribute('width', '100');
                    rect.setAttribute('height', '100');
                    rect.setAttribute('rx', '10');
                    rect.setAttribute('fill', fillColor);

                    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                    text.setAttribute('class', 'node-label');
                    text.setAttribute('x', x + 50);
                    text.setAttribute('y', y + 80);
                    text.textContent = nodeName;

                    newNode.appendChild(rect);
                    newNode.appendChild(symbol);
                    newNode.appendChild(text);

                    // 添加点击事件
                    newNode.addEventListener('click', function() {
                        nodes.forEach(n => n.classList.remove('active'));
                        connections.forEach(c => c.classList.remove('active'));
                        this.classList.add('active');
                        infoPanel.style.display = 'block';
                        infoContent.innerHTML = this.getAttribute('data-info');
                    });

                    svg.appendChild(newNode);

                    // 更新节点列表
                    nodes = document.querySelectorAll('.node');
                }
            });

            // 创建网络设备符号
            function createNetworkSymbol() {
                const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');

                const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                rect.setAttribute('x', 20);
                rect.setAttribute('y', 20);
                rect.setAttribute('width', '60');
                rect.setAttribute('height', '40');
                rect.setAttribute('fill', '#fff');
                rect.setAttribute('rx', '5');

                const line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                line1.setAttribute('x1', 20);
                line1.setAttribute('y1', 30);
                line1.setAttribute('x2', 80);
                line1.setAttribute('y2', 30);
                line1.setAttribute('stroke', '#2c3e50');
                line1.setAttribute('stroke-width', '2');

                const line2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                line2.setAttribute('x1', 40);
                line2.setAttribute('y1', 20);
                line2.setAttribute('x2', 40);
                line2.setAttribute('y2', 60);
                line2.setAttribute('stroke', '#2c3e50');
                line2.setAttribute('stroke-width', '2');

                const line3 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                line3.setAttribute('x1', 60);
                line3.setAttribute('y1', 20);
                line3.setAttribute('x2', 60);
                line3.setAttribute('y2', 60);
                line3.setAttribute('stroke', '#2c3e50');
                line3.setAttribute('stroke-width', '2');

                group.appendChild(rect);
                group.appendChild(line1);
                group.appendChild(line2);
                group.appendChild(line3);

                return group;
            }

            // 创建服务器符号
            function createServerSymbol() {
                const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');

                const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                rect.setAttribute('x', 20);
                rect.setAttribute('y', 20);
                rect.setAttribute('width', '60');
                rect.setAttribute('height', '40');
                rect.setAttribute('fill', '#fff');
                rect.setAttribute('rx', '3');

                for (let i = 0; i < 3; i++) {
                    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    line.setAttribute('x1', 25 + i*15);
                    line.setAttribute('y1', 30 + i*5);
                    line.setAttribute('x2', 55 + i*15);
                    line.setAttribute('y2', 30 + i*5);
                    line.setAttribute('stroke', '#2c3e50');
                    line.setAttribute('stroke-width', '1');
                    group.appendChild(line);
                }

                return group;
            }

            // 创建存储设备符号
            function createStorageSymbol() {
                const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');

                const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                rect.setAttribute('x', 20);
                rect.setAttribute('y', 20);
                rect.setAttribute('width', '60');
                rect.setAttribute('height', '50');
                rect.setAttribute('fill', '#fff');
                rect.setAttribute('rx', '3');

                for (let i = 0; i < 3; i++) {
                    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    line.setAttribute('x1', 30);
                    line.setAttribute('y1', 30 + i*10);
                    line.setAttribute('x2', 70);
                    line.setAttribute('y2', 30 + i*10);
                    line.setAttribute('stroke', '#8e44ad');
                    line.setAttribute('stroke-width', '2');
                    group.appendChild(line);
                }

                return group;
            }

            // 创建安全设备符号
            function createSecuritySymbol() {
                const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');

                const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                rect.setAttribute('x', 20);
                rect.setAttribute('y', 20);
                rect.setAttribute('width', '60');
                rect.setAttribute('height', '60');
                rect.setAttribute('fill', '#fff');
                rect.setAttribute('rx', '5');

                for (let i = 0; i < 2; i++) {
                    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    line.setAttribute('x1', 20);
                    line.setAttribute('y1', 30 + i*20);
                    line.setAttribute('x2', 80);
                    line.setAttribute('y2', 30 + i*20);
                    line.setAttribute('stroke', '#c0392b');
                    line.setAttribute('stroke-width', '2');
                    group.appendChild(line);
                }

                return group;
            }

            // 切换连接线显示
            document.getElementById('toggleConnectionsBtn').addEventListener('click', function() {
                if (connectionsVisible) {
                    connections.forEach(conn => conn.style.display = 'none');
                    connectionsVisible = false;
                    this.textContent = '显示连接线';
                } else {
                    connections.forEach(conn => conn.style.display = 'block');
                    connectionsVisible = true;
                    this.textContent = '隐藏连接线';
                }
            });

            // 导出为PNG
            document.getElementById('exportBtn').addEventListener('click', function() {
                alert('导出功能需要服务器端支持。在实际应用中，可以使用html2canvas或类似库实现此功能。');
            });
        });
    </script>
</body>
</html>